using System;
namespace simulation
{
	public class BinarySystem : IMechanicalSystem
	{
		public double [] m_;
		public double [] x_;
		public double [] y_;
		public double [] vx_;
		public double [] vy_;
		
		public BinarySystem (double []m, double [] x, double []y, double []vx, double []vy) 
		{
			m_ = new double[2];
			x_ = new double[2];
			y_ = new double[2];
			vx_ = new double[2];
			vy_ = new double[2];
			m_[0] = m[0];
			x_[0] = x[0];
			vx_[0] = vx[0];
			y_[0] = y[0];
			vy_[0] = vy[0];
			m_[1] = m[1];
			x_[1] = x[1];
			vx_[1] = vx[1];
			y_[1] = y[1];
			vy_[1] = vy[1];
		}

		public BinarySystem ()
		{
			m_ = new double[2];
			x_ = new double[2];
			y_ = new double[2];
			vx_ = new double[2];
			vy_ = new double[2];
		}
		
		public object Clone()
		{
			return new BinarySystem(m_, x_, y_, vx_, vy_);
		}

		public void toCanonical(ref CanonicalSystem s)
		{
			s.q_[0] = x_[0];
			s.q_[1] = y_[0];
			s.q_[2] = x_[1];
			s.q_[3] = y_[1];
			s.q_[4] = vx_[0];
			s.q_[5] = vy_[0];
			s.q_[6] = vx_[1];
			s.q_[7] = vy_[1];
			//s.qdot_[0] = v_;
			//s.qdot_[1] = 0 / m_;
		}
		
		public void createCanonical(out CanonicalSystem s)
		{
			s = new CanonicalSystem (8);
			s.q_[0] = x_[0];
			s.q_[1] = y_[0];
			s.q_[2] = x_[1];
			s.q_[3] = y_[1];
			s.q_[4] = vx_[0];
			s.q_[5] = vy_[0];
			s.q_[6] = vx_[1];
			s.q_[7] = vy_[1];
		}
		
		public void fromCanonical(CanonicalSystem s)
		{
			x_[0] = s.q_[0];
			y_[0] = s.q_[1];
			x_[1] = s.q_[2];
			y_[1] = s.q_[3];
			vx_[0] = s.q_[4];
			vy_[0] = s.q_[5];
			vx_[1] = s.q_[6];
			vy_[1] = s.q_[7];
		}
		
		public override string ToString ()
		{
			 return "x = " + x_.ToString() + " y = " + y_.ToString() +
				" vx = " + vx_.ToString() + " vy = " + vy_.ToString();
		}
		
		public void draw (Gdk.Window win, double x_unit, double y_unit, Gdk.Rectangle clear)
		{
			int width, height;			

			Gdk.GC gc = new Gdk.GC (win);
	
			win.ClearArea(clear, true);
			win.GetSize(out width, out height);
			
			gc.Fill = Gdk.Fill.Solid;
			Gdk.Color red_color = new Gdk.Color (0xff, 0, 0);
			Gdk.Color blue_color = new Gdk.Color (0, 0, 0xff);
			Gdk.Colormap colormap = Gdk.Colormap.System;
			colormap.AllocColor(ref red_color, true, true);
			colormap.AllocColor(ref blue_color, true, true);
	
			gc.Foreground = red_color;
			win.DrawArc(gc, true, width / 2 + (int)(x_[0] * x_unit), height / 2 - (int) (y_[0] * y_unit), 5, 5, 0, 360*64); // full circle
	
			gc.Foreground = blue_color;
			win.DrawArc(gc, true, width / 2 + (int)(x_[1] * x_unit), height / 2 - (int) (y_[1] * y_unit), 5, 5, 0, 360*64);
		}

		public Gdk.Rectangle GetRect(Gdk.Window win, double x_unit, double y_unit)
		{			
			int width, height;
			win.GetSize(out width, out height);
			
			int x0 = width / 2 + (int)(x_[0] * x_unit), x1 = width / 2 + (int)(x_[1] * x_unit);
			int y0 = height / 2 - (int) (y_[0] * y_unit), y1 = height / 2 - (int) (y_[1] * y_unit);
			
			int xmin = Math.Min(x0,x1) - 5, xmax = Math.Max(x0,x1)+5;
			int ymin = Math.Min(y0,y1) - 5, ymax = Math.Max(y0,y1)+5;
			
			Gdk.Rectangle rect = new Gdk.Rectangle (xmin, ymin, xmax-xmin+1, ymax-ymin+1);
			
			return rect;
		}
	}

	class GravityForceBinary : Force<BinarySystem>
	{
		public override void getDot(BinarySystem s, ref double[] qdot)
		{
			qdot[0] = s.vx_[0];
			qdot[1] = s.vy_[0];
			qdot[2] = s.vx_[1];
			qdot[3] = s.vy_[1];
			
			double G = .1;
			double dx = s.x_[0] - s.x_[1], dy = s.y_[0] - s.y_[1];
			double r3 = Math.Pow(dx * dx + dy * dy, 1.5);
			qdot[4] = -s.m_[1] * G / r3 * (dx);
			qdot[5] = -s.m_[1] * G / r3 * (dy);
			qdot[6] = -s.m_[0] * G / r3 * (-dx);
			qdot[7] = -s.m_[0] * G / r3 * (-dy);
		}
	}
}

